home *** CD-ROM | disk | FTP | other *** search
- /* Copyright William Schelter. All rights reserved.
-
- Stratified Garbage Collection (SGC)
-
- Write protects pages to tell which ones have been written
- to recently, for more efficient garbage collection.
-
- */
-
- #ifdef BSD
- /* ulong may have been defined in mp.h but the define is no longer needed */
- #undef ulong
- #include <sys/mman.h>
- #define PROT_READ_WRITE (PROT_READ | PROT_WRITE |PROT_EXEC)
- #endif
- #ifdef AIX3
- #include <sys/vmuser.h>
- #define PROT_READ RDONLY
- #define PROT_READ_WRITE UDATAKEY
- int mprotect();
- #endif
-
- #include <signal.h>
-
- void segmentation_catcher();
-
-
- #define sgc_mark_pack_list(u) \
- do {register object xtmp = u; \
- while (xtmp != Cnil) \
- {if (ON_WRITABLE_PAGE(xtmp)) xtmp->d.m = TRUE; \
- sgc_mark_object(xtmp->c.c_car); \
- xtmp=xtmp->c.c_cdr;}}while(0)
-
-
- #ifdef SDEBUG
- object sdebug;
- joe1(){;}
- #endif
-
- sgc_mark_cons(x)
- object x;
- {
- cs_check(x);
-
- /* x is already marked. */
-
- BEGIN:
- #ifdef SDEBUG
- if(x==sdebug) joe1();
- #endif
- sgc_mark_object(x->c.c_car);
- #ifdef OLD
- IF_WRITABLE(x->c.c_car, goto MARK_CAR;);
- goto MARK_CDR;
-
- MARK_CAR:
- if (x->c.c_car->c.m ==0)
- {if (type_of(x->c.c_car) == t_cons)
- {
- x->c.c_car->c.m = TRUE;
- sgc_mark_cons(x->c.c_car);
- }
- else
- sgc_mark_object1(x->c.c_car);}
- #endif
- MARK_CDR:
- x = x->c.c_cdr;
- IF_WRITABLE(x, goto WRITABLE_CDR;);
- return;
- WRITABLE_CDR:
- if (x->d.m) return;
- if (type_of(x) == t_cons) {
- x->c.m = TRUE;
- goto BEGIN;
- }
- sgc_mark_object1(x);
- }
-
-
- /* Whenever two arrays are linked together by displacement,
- if one is live, the other will be made live */
- #define sgc_mark_displaced_field(ar) sgc_mark_object(ar->a.a_displaced)
-
-
- /* structures and arrays of type t, need to be marked if their
- bodies are not write protected even if the headers are.
- So we should keep these on pages particular to them.
- Actually we will change structure sets to touch the structure
- header, that way we won't have to keep the headers in memory.
- This takes only 1.47 as opposed to 1.33 microseconds per set.
- */
- sgc_mark_object1(x)
- object x;
- {
- int i, j;
- object *p;
- char *cp;
- object y;
-
- cs_check(x);
- BEGIN:
- #ifdef SDEBUG
- if (x == OBJNULL || !ON_WRITABLE_PAGE(x))
- return;
- IF_WRITABLE(x,goto OK);
- joe();
-
- OK:
- if (x->d.m)
- return;
-
- if(x==sdebug) joe1();
- #endif
- x->d.m = TRUE;
- switch (type_of(x)) {
- case t_fixnum:
- break;
-
- case t_ratio:
- sgc_mark_object(x->rat.rat_num);
- x = x->rat.rat_den;
- IF_WRITABLE(x,if(x->d.m==0) goto BEGIN);
-
- case t_shortfloat:
- break;
-
- case t_longfloat:
- break;
-
- case t_complex:
- sgc_mark_object(x->cmp.cmp_imag);
- x = x->cmp.cmp_real;
- IF_WRITABLE(x,if(x->d.m==0) goto BEGIN);
-
- case t_character:
- break;
-
- case t_symbol:
- IF_WRITABLE(x->s.s_plist,if(x->s.s_plist->d.m==0)
- {x->s.s_plist->d.m=TRUE;
- sgc_mark_cons(x->s.s_plist);});
- sgc_mark_object(x->s.s_gfdef);
- sgc_mark_object(x->s.s_dbind);
- /* do {int xxx= (((int)(char *)(x->s.s_dbind)-0)>>12);
- if((xxx & (-16384) ==0)
- && (sgc_type_map[xxx] & (4 | 1)))
- {if((x->s.s_dbind)->d.m==0)
- sgc_mark_object1(x->s.s_dbind);}} while(0); */
- if (x->s.s_self == NULL)
- break;
- /* to do */
- if ((int)what_to_collect >= (int)t_contiguous) {
- if (inheap(x->s.s_self)) {
- if (what_to_collect == t_contiguous)
- mark_contblock(x->s.s_self,
- x->s.s_fillp);
- } else if(SGC_RELBLOCK_P(x->s.s_self))
- x->s.s_self =
- copy_relblock(x->s.s_self, x->s.s_fillp);
- }
- break;
-
- case t_package:
- sgc_mark_object(x->p.p_name);
- sgc_mark_object(x->p.p_nicknames);
- sgc_mark_object(x->p.p_shadowings);
- sgc_mark_object(x->p.p_uselist);
- sgc_mark_object(x->p.p_usedbylist);
- if (what_to_collect != t_contiguous)
- break;
- if (x->p.p_internal != NULL)
- mark_contblock((char *)(x->p.p_internal),
- x->p.p_internal_size*sizeof(object));
- if (x->p.p_external != NULL)
- mark_contblock((char *)(x->p.p_external),
- x->p.p_external_size*sizeof(object));
- break;
-
- case t_cons:
- /*
- sgc_mark_object(x->c.c_car);
- x = x->c.c_cdr;
- goto BEGIN;
- */
- sgc_mark_cons(x);
- break;
-
- case t_hashtable:
- sgc_mark_object(x->ht.ht_rhsize);
- sgc_mark_object(x->ht.ht_rhthresh);
- if (x->ht.ht_self == NULL)
- break;
- for (i = 0, j = x->ht.ht_size; i < j; i++) {
- sgc_mark_object(x->ht.ht_self[i].hte_key);
- sgc_mark_object(x->ht.ht_self[i].hte_value);
- }
- if ((short)what_to_collect >= (short)t_contiguous) {
- if (inheap(x->ht.ht_self)) {
- if (what_to_collect == t_contiguous)
- mark_contblock((char *)(x->ht.ht_self),
- j * sizeof(struct htent));
- } else if(SGC_RELBLOCK_P(x->ht.ht_self))
- x->ht.ht_self = (struct htent *)
- copy_relblock((char *)(x->ht.ht_self),
- j * sizeof(struct htent));
- }
- break;
-
- case t_array:
- if ((x->a.a_displaced) != Cnil)
- sgc_mark_displaced_field(x);
- if ((int)what_to_collect >= (int)t_contiguous &&
- x->a.a_dims != NULL) {
- if (inheap(x->a.a_dims)) {
- if (what_to_collect == t_contiguous)
- mark_contblock((char *)(x->a.a_dims),
- sizeof(int)*x->a.a_rank);
- } else if(SGC_RELBLOCK_P(x->a.a_dims))
- x->a.a_dims = (int *)
- copy_relblock((char *)(x->a.a_dims),
- sizeof(int)*x->a.a_rank);
- }
- if ((enum aelttype)x->a.a_elttype == aet_ch)
- goto CASE_STRING;
- if ((enum aelttype)x->a.a_elttype == aet_bit)
- goto CASE_BITVECTOR;
- if ((enum aelttype)x->a.a_elttype == aet_object)
- goto CASE_GENERAL;
-
- CASE_SPECIAL:
- cp = (char *)(x->fixa.fixa_self);
- if (cp == NULL)
- break;
- /* set j to the size in char of the body of the array */
-
- switch((enum aelttype)x->a.a_elttype){
- case aet_lf:
- j= sizeof(longfloat)*x->lfa.lfa_dim;
- if (((int)what_to_collect >= (int)t_contiguous) &&
- !(inheap(cp)) && SGC_RELBLOCK_P(x->a.a_self))
- ROUND_RB_POINTERS_DOUBLE;
- break;
- case aet_char:
- case aet_uchar:
- j=sizeof(char)*x->a.a_dim;
- break;
- case aet_short:
- case aet_ushort:
- j=sizeof(short)*x->a.a_dim;
- break;
- default:
- j=sizeof(fixnum)*x->fixa.fixa_dim;}
-
- goto COPY;
-
- CASE_GENERAL:
- p = x->a.a_self;
- if (p == NULL
- #ifdef HAVE_ALLOCA
- || (char *)p >= core_end
- #endif
-
- )
- break;
- if (x->a.a_displaced->c.c_car == Cnil)
- for (i = 0, j = x->a.a_dim; i < j; i++)
- if (ON_WRITABLE_PAGE(&p[i]))
- sgc_mark_object(p[i]);
- cp = (char *)p;
- j *= sizeof(object);
- COPY:
- if ((int)what_to_collect >= (int)t_contiguous) {
- if (inheap(cp)) {
- if (what_to_collect == t_contiguous)
- mark_contblock(cp, j);
- }
- else if (!SGC_RELBLOCK_P(cp)) ;
- else if (x->a.a_displaced == Cnil)
- x->a.a_self = (object *)copy_relblock(cp, j);
- else if (x->a.a_displaced->c.c_car == Cnil) {
- i = (int)(object *)copy_relblock(cp, j)
- - (int)(x->a.a_self);
- adjust_displaced(x, i);
- }
- }
- break;
-
- case t_vector:
- if ((x->v.v_displaced) != Cnil)
- sgc_mark_displaced_field(x);
- if ((enum aelttype)x->v.v_elttype == aet_object)
- goto CASE_GENERAL;
- else
- goto CASE_SPECIAL;
-
- case t_bignum:
- if ((int)what_to_collect >= (int)t_contiguous) {
- j = x->big.big_length;
- cp = (char *)x->big.big_self;
- if (cp == NULL)
- break;
- if (j != lg(MP(x)) &&
- /* we don't bother to zero this register,
- and its contents may get over written */
- ! (x == big_register_1 &&
- (int)(cp) <= top &&
- (int) cp >= bot))
-
- printf("bad length 0x%x ",x);
- j = j * sizeof(int);
- cp = (char *)MP(x);
- if (inheap(cp)) {
- if (what_to_collect == t_contiguous)
- mark_contblock(cp, j);
- } else
- x->big.big_self = (long *)copy_relblock(cp, j);}
- break;
-
-
- CASE_STRING:
- case t_string:
- if ((x->st.st_displaced) != Cnil)
- sgc_mark_displaced_field(x);
- j = x->st.st_dim;
- cp = x->st.st_self;
- if (cp == NULL)
- break;
-
- COPY_STRING:
- if ((int)what_to_collect >= (int)t_contiguous) {
- if (inheap(cp)) {
- if (what_to_collect == t_contiguous)
- mark_contblock(cp, j);
- }
- else if (!SGC_RELBLOCK_P(cp)) ;
- else if (x->st.st_displaced == Cnil)
- x->st.st_self = copy_relblock(cp, j);
- else if (x->st.st_displaced->c.c_car == Cnil) {
- i = copy_relblock(cp, j) - cp;
- adjust_displaced(x, i);
- }
- }
- break;
-
- CASE_BITVECTOR:
- case t_bitvector:
- if ((x->bv.bv_displaced) != Cnil)
- sgc_mark_displaced_field(x);
- /* We make bitvectors multiple of sizeof(int) in size allocated
- Assume 8 = number of bits in char */
-
- #define W_SIZE (8*sizeof(int))
- j= sizeof(int) *
- ((x->bv.bv_offset + x->bv.bv_dim + W_SIZE -1)/W_SIZE);
- cp = x->bv.bv_self;
- if (cp == NULL)
- break;
- goto COPY_STRING;
-
- case t_structure:
- sgc_mark_object(x->str.str_def);
- p = x->str.str_self;
- if (p == NULL)
- break;
- {object def=x->str.str_def;
- unsigned char * s_type = &SLOT_TYPE(def,0);
- unsigned short *s_pos= & SLOT_POS(def,0);
- for (i = 0, j = S_DATA(def)->length; i < j; i++)
- if (s_type[i]==0 &&
- ON_WRITABLE_PAGE(& STREF(object,x,s_pos[i]))
- )
- sgc_mark_object(STREF(object,x,s_pos[i]));
- if ((int)what_to_collect >= (int)t_contiguous) {
- if (inheap(x->str.str_self)) {
- if (what_to_collect == t_contiguous)
- mark_contblock((char *)p,
- S_DATA(def)->size);
-
- } else if(SGC_RELBLOCK_P(p))
- x->str.str_self = (object *)
- copy_relblock((char *)p, S_DATA(def)->size);
- }}
- break;
-
- case t_stream:
- switch (x->sm.sm_mode) {
- case smm_input:
- case smm_output:
- case smm_io:
- case smm_probe:
- sgc_mark_object(x->sm.sm_object0);
- sgc_mark_object(x->sm.sm_object1);
- if (saving_system)
- {FILE *fp = x->sm.sm_fp;
- if (fp != 0 && fp != stdin && fp !=stdout
- )
- {fclose(fp);
- x->sm.sm_fp=0;
- }}
- else
- if (what_to_collect == t_contiguous &&
- x->sm.sm_fp &&
- x->sm.sm_buffer)
- mark_contblock(x->sm.sm_buffer, BUFSIZ);
- break;
-
- case smm_synonym:
- sgc_mark_object(x->sm.sm_object0);
- break;
-
- case smm_broadcast:
- case smm_concatenated:
- sgc_mark_object(x->sm.sm_object0);
- break;
-
- case smm_two_way:
- case smm_echo:
- sgc_mark_object(x->sm.sm_object0);
- sgc_mark_object(x->sm.sm_object1);
- break;
-
- case smm_string_input:
- case smm_string_output:
- sgc_mark_object(x->sm.sm_object0);
- break;
- #ifdef USER_DEFINED_STREAMS
- case smm_user_defined:
- sgc_mark_object(x->sm.sm_object0);
- sgc_mark_object(x->sm.sm_object1);
- break;
- #endif
- default:
- error("mark stream botch");
- }
- break;
-
- case t_random:
- break;
-
- case t_readtable:
- if (x->rt.rt_self == NULL)
- break;
- if (what_to_collect == t_contiguous)
- mark_contblock((char *)(x->rt.rt_self),
- RTABSIZE*sizeof(struct rtent));
- for (i = 0; i < RTABSIZE; i++) {
- sgc_mark_object(x->rt.rt_self[i].rte_macro);
- if (x->rt.rt_self[i].rte_dtab != NULL) {
- /**/
- if (what_to_collect == t_contiguous)
- mark_contblock((char *)(x->rt.rt_self[i].rte_dtab),
- RTABSIZE*sizeof(object));
- for (j = 0; j < RTABSIZE; j++)
- sgc_mark_object(x->rt.rt_self[i].rte_dtab[j]);
- /**/
- }
- }
- break;
-
- case t_pathname:
- sgc_mark_object(x->pn.pn_host);
- sgc_mark_object(x->pn.pn_device);
- sgc_mark_object(x->pn.pn_directory);
- sgc_mark_object(x->pn.pn_name);
- sgc_mark_object(x->pn.pn_type);
- sgc_mark_object(x->pn.pn_version);
- break;
-
- case t_cfun:
- case t_sfun:
- case t_vfun:
- case t_gfun:
- sgc_mark_object(x->cf.cf_name);
- sgc_mark_object(x->cf.cf_data);
- break;
-
- case t_cfdata:
-
- if (x->cfd.cfd_self != NULL)
- {int i=x->cfd.cfd_fillp;
- while(i-- > 0)
- sgc_mark_object(x->cfd.cfd_self[i]);}
- if (x->cfd.cfd_start == NULL)
- break;
- if (what_to_collect == t_contiguous) {
- if (!MAYBE_DATA_P((x->cfd.cfd_start)) ||
- get_mark_bit((int *)(x->cfd.cfd_start)))
- break;
- mark_contblock(x->cfd.cfd_start, x->cfd.cfd_size);}
- break;
- case t_cclosure:
- sgc_mark_object(x->cc.cc_name);
- sgc_mark_object(x->cc.cc_env);
- sgc_mark_object(x->cc.cc_data);
- if (what_to_collect == t_contiguous) {
- if (x->cc.cc_turbo != NULL)
- mark_contblock((char *)(x->cc.cc_turbo-1),
- (1+fix(*(x->cc.cc_turbo-1)))*sizeof(object));
- }
- break;
-
- case t_spice:
- break;
- case t_fat_string:
- mark_fat_string(x);
- break;
- case t_dclosure:
- break;
- default:
- #ifdef DEBUG
- if (debug)
- printf("\ttype = %d\n", type_of(x));
- #endif
- error("mark botch");
- }
-
- }
-
-
-
- sgc_mark_stack_carefully(top,bottom,offset)
- int *bottom,*top;
- {int p,m,pageoffset;
- object x;
- struct typemanager *tm;
- register int *j;
-
- /* if either of these happens we are marking the C stack
- and need to use a local */
-
- if (top==0) top = c_stack_where;
- if (bottom==0) bottom= c_stack_where;
-
- /* On machines which align local pointers on multiple of 2 rather
- than 4 we need to mark twice
- */
-
- if (offset) {sgc_mark_stack_carefully(bottom,(((char *) top) +offset),0);}
- for (j=top ; j >= bottom ; j--)
- {if (VALID_DATA_ADDRESS_P(*j)
- && type_map[(p=page(*j))]< (char)t_end)
- {pageoffset=((char *)*j - pagetochar(p));
- tm=tm_of((enum type) type_map[p]);
- x= (object)
- ((char *)(*j) -
- ((pageoffset=((char *)*j - pagetochar(p))) %
- tm->tm_size));
- if ((pageoffset < (tm->tm_size * tm->tm_nppage))
- && (m=x->d.m) != FREE)
- {if (m==TRUE) continue;
- if (m!=0)
- {fprintf(stdout,
- "**bad value %d of d.m in gbc page %d skipping mark**"
- ,m,p);fflush(stdout);
- continue;
- };
- sgc_mark_object(x);}}}}
-
-
- sgc_mark_phase()
- {
- STATIC object *p;
- STATIC int i, j, k, n;
- STATIC struct package *pp;
- STATIC object s, l, *lp;
- STATIC bds_ptr bdp;
- STATIC frame_ptr frp;
- STATIC ihs_ptr ihsp;
- STATIC char *cp;
-
- sgc_mark_object(Cnil);
- sgc_mark_object(Ct);
-
-
-
- /* mark all non recent data on writable pages */
- {int t,i=page(heap_end);
- struct typemanager *tm;
- char *p;
-
- while (--i >= 0)
- {if (WRITABLE_PAGE_P(i)
- && (t=type_map[i]) < (int) t_end);
- else continue;
- tm=tm_of(t);
- p=pagetochar(i);
- if ( t == t_cons)
- for (j = tm->tm_nppage; --j >= 0; p += sizeof(struct cons))
- {object x = (object) p;
- if (SGC_OR_M(x)) continue;
- if (x->d.t==t_cons) {x->d.m = TRUE; sgc_mark_cons(x);}
- else
- sgc_mark_object1(x);
- }
- else
- {int size=tm->tm_size;
- for (j = tm->tm_nppage; --j >= 0; p += size)
- {object x = (object) p;
- if (SGC_OR_M(x)) continue;
- sgc_mark_object1(x);
- }}}}
-
-
- sgc_mark_stack_carefully(vs_top-1,vs_org,0);
- clear_stack(vs_top,vs_limit);
- sgc_mark_stack_carefully(MVloc,MVloc+(sizeof(MVloc)/sizeof(object)),0);
- /*
- for (p = vs_org; p < vs_top; p++) {
- if (p && (inheap(*p)))
- sgc_mark_object(*p);
- }
- */
- #ifdef DEBUG
- if (debug) {
- printf("value stack marked\n");
- fflush(stdout);
- }
- #endif
-
- for (bdp = bds_org; bdp<=bds_top; bdp++) {
- sgc_mark_object(bdp->bds_sym);
- sgc_mark_object(bdp->bds_val);
- }
-
- for (frp = frs_org; frp <= frs_top; frp++)
- sgc_mark_object(frp->frs_val);
-
- for (ihsp = ihs_org; ihsp <= ihs_top; ihsp++)
- sgc_mark_object(ihsp->ihs_function);
-
- for (i = 0; i < mark_origin_max; i++)
- sgc_mark_object(*mark_origin[i]);
- for (i = 0; i < mark_origin_block_max; i++)
- for (j = 0; j < mark_origin_block[i].mob_size; j++)
- sgc_mark_object(mark_origin_block[i].mob_addr[j]);
-
- for (pp = pack_pointer; pp != NULL; pp = pp->p_link)
- sgc_mark_object((object)pp);
- #ifdef KCLOVM
- if (ovm_process_created)
- sgc_mark_all_stacks();
- #endif
-
-
- if (debug) {
- printf("symbol navigation\n");
- fflush(stdout);
- }
- {int size;
-
- for (pp = pack_pointer; pp != NULL; pp = pp->p_link) {
- size = pp->p_internal_size;
- if (pp->p_internal != NULL)
- for (i = 0; i < size; i++)
- sgc_mark_pack_list(pp->p_internal[i]);
- size = pp->p_external_size;
- if (pp->p_external != NULL)
- for (i = 0; i < size; i++)
- sgc_mark_pack_list(pp->p_external[i]);
- }}
-
-
- mark_c_stack(0,N_RECURSION_REQD,sgc_mark_stack_carefully);
-
- }
-
- sgc_sweep_phase()
- {
- STATIC int i, j, k;
- STATIC object x;
- STATIC char *p;
- STATIC int *ip;
- STATIC struct typemanager *tm;
- STATIC object f;
- int size;
-
- Cnil->s.m = FALSE;
- Ct->s.m = FALSE;
-
- #ifdef DEBUG
- if (debug)
- printf("type map\n");
- #endif
- for (i = 0; i < maxpage; i++) {
- if (type_map[i] == (int)t_contiguous) {
- if (debug) {
- printf("-");
- /*
- fflush(stdout);
- */
- continue;
- }
- }
- if (type_map[i] >= (int)t_end)
- continue;
-
- tm = tm_of((enum type)type_map[i]);
-
- /*
- general sweeper
- */
-
- #ifdef DEBUG
- if (debug) {
- printf("%c", tm->tm_name[0]);
- /*
- fflush(stdout);
- */
- }
- #endif
- if (!WRITABLE_PAGE_P(i)) continue;
- p = pagetochar(i);
- f = tm->tm_free;
- k = 0;
- size=tm->tm_size;
- if (SGC_PAGE_P(i)) {
- for (j = tm->tm_nppage; --j >= 0; p += size) {
- x = (object)p;
-
- if (x->d.m == FREE)
- continue;
- else if (x->d.m) {
- x->d.m = FALSE;
- continue;
- }
- if(x->d.s == SGC_NORMAL)
- continue;
-
- /* it is ok to free x */
-
- #ifdef OLD_DISPLACE
- /* old_displace: from might be free, to not */
- if(x->d.t >=t_array && x->d.t <= t_bitvector)
- {
- /* case t_array:
- case t_vector:
- case t_string:
- case t_bitvector:
- */
- if (x->a.a_displaced->c.c_car != Cnil)
- {undisplace(x);
- /* The cons x->a.a_displaced cons has been saved,
- so as to save the pointer to x->a.a_displaced->c.c_car;
- However any arrays in its cdr, must have been
- freed, or we would not be freeing x. To avoid
- having a cons with trash in the cdr we set the
- cdr to nil
- */
- x->a.a_displaced->c.c_cdr = Cnil;}
- }
- #endif OLD_DISPLACE
- ((struct freelist *)x)->f_link = f;
- x->d.m = FREE;
- x->d.s = (int)SGC_RECENT;
- f = x;
- k++;
- }
- tm->tm_free = f;
- tm->tm_nfree += k;
- }
- else /*non sgc_page */
- for (j = tm->tm_nppage; --j >= 0; p += size) {
- x = (object)p;
-
- if (x->d.m == TRUE) x->d.m=FALSE;
- }
-
-
- NEXT_PAGE:
- ;
- }
- #ifdef DEBUG
- if (debug) {
- putchar('\n');
- fflush(stdout);
- }
- #endif
- }
-
-
- sgc_contblock_sweep_phase()
- {
- STATIC int i, j;
- STATIC char *s, *e, *p, *q;
- STATIC struct contblock *cbp;
-
- cb_pointer = NULL;
- ncb = 0;
- for (i = 0; i < maxpage;) {
- if (type_map[i] != (int)t_contiguous
- || !SGC_PAGE_P(i))
- {
- i++;
- continue;
- }
- for (j = i+1;
- j < maxpage && type_map[j] == (int)t_contiguous
- && SGC_PAGE_P(j)
- ;
- j++)
- ;
- s = pagetochar(i);
- e = pagetochar(j);
- for (p = s; p < e;) {
- if (get_mark_bit((int *)p)) {
- p += 4;
- continue;
- }
- q = p + 4;
- while (q < e) {
- if (!get_mark_bit((int *)q)) {
- q += 4;
- continue;
- }
- break;
- }
- insert_contblock(p, q - p);
- p = q + 4;
- }
- i = j + 1;
- }
- #ifdef DEBUG
- if (debug) {
- for (cbp = cb_pointer; cbp != NULL; cbp = cbp->cb_link)
- printf("%d-byte contblock\n", cbp->cb_size);
- fflush(stdout);
- }
- #endif
- }
-
-
-
- #define PAGE_ROUND_UP(adr) \
- ((char *)(PAGESIZE*(((int)(adr)+PAGESIZE -1) >> PAGEWIDTH)))
-
- char *old_rb_start;
-
- #undef tm
- int bug1,bug2;
-
-
- #ifdef SDEBUG
- sgc_count(yy)
- object yy;
- {int count=0;
- object y=yy;
- while(y)
- {count++;
- y=F_LINK(y);}
- printf("[length %x = %d]",yy,count);
- fflush(stdout);
- }
-
- #endif
- /* count writable pages excluding the hole */
- sgc_count_writable(end)
- int end;
- { int j = first_protectable_page -1;
- int count = 0;
- int hp_end= page(heap_end);
- while(j++ < hp_end)
- if (WRITABLE_PAGE_P(j)) count++;
- j= page(rb_start);
- while(j++ < end)
- if (WRITABLE_PAGE_P(j)) count++;
- return count;}
-
-
- sgc_count_type(t)
- int t;
- {int j = first_protectable_page -1;
- int end = page(core_end);
- int count=0;
- while(j++ < end)
- if (type_map[j]==t && SGC_PAGE_P(j))
- count++;
- return count;}
-
-
-
-
-
- sgc_start()
- {int i;
- int np;
- int bug;
- short free_map[MAXPAGE];
- object f, fr[(int)t_end];
- struct typemanager *tm;
- int npages;
- if (sgc_type_map[page((&sgc_type_map[0]))] != SGC_PERM_WRITABLE )
- {perm_writable(&sgc_type_map[0],sizeof(sgc_type_map));
- }
- if (sgc_enabled)
- return 1;
- sgc_type_map[0]=0;
- AGAIN:
- i=npages=page(core_end);
- while (i--> 0)
- sgc_type_map[i] = sgc_type_map[i] & SGC_PERM_WRITABLE ;
-
- for (i= t_start; i < t_contiguous ; i++)
- if (TM_BASE_TYPE_P(i) && (np=(tm=tm_of(i))->tm_sgc))
- FIND_FREE_PAGES:
- {
- int maxp=0;
- int j;
- int minfree = tm->tm_sgc_minfree;
- int count,tm_sgc;
- bzero(free_map,npages*sizeof(short));
- f = tm->tm_free;
- count=0;
- while (f!=0)
- {free_map[j=page(f)]++;
- if (j>=maxp) maxp=j;
- #ifdef DEBUG
- count++;
- #endif
- f= F_LINK(f);
- }
- #ifdef DEBUG
- if (count!=tm->tm_nfree)
- {printf("[Count differed type(%d)nfree= %d in freelist %d]\n"
- ,tm->tm_type,tm->tm_nfree,
- count);fflush(stdout);}
- #endif
- for(j=0,count=0; j <= maxp ;j++)
- {if (free_map[j] >= minfree)
- {sgc_type_map[j] |= (SGC_PAGE_FLAG | SGC_TEMP_WRITABLE);
- ++count;
- if (count >= tm->tm_sgc_max)
- break;
- }}
-
- /* don't do any more allocations for this type if saving system */
- if (saving_system) continue;
-
- if (count < tm->tm_sgc)
- /* try to get some more free pages of type i */
- { int n = tm->tm_sgc - count;
- int again=0,nfree = tm->tm_nfree;
- char *p=alloc_page(n);
- if (tm->tm_nfree > nfree) again=1; /* gc freed some objects */
- while (n-- > 0)
- {(sgc_enabled=1,add_page_to_freelist(p,tm),sgc_enabled=0);
- p += PAGESIZE;}
- if (again) goto FIND_FREE_PAGES; }}
- /* Now allocate the sgc relblock. We do this as the tail
- end of the ordinary rb. */
- {int want;
- char *new;
- tm=tm_of(t_relocatable);
- want =((int) (rb_end - rb_pointer) >> PAGEWIDTH);
- if (want < tm->tm_sgc) want = tm->tm_sgc;
- else { want = (want < 4 ? want : want -2);}
-
- FINALE:
- {old_rb_start=rb_start;
- if(!saving_system)
- { new=alloc_relblock(want*PAGESIZE);
- new= PAGE_ROUND_UP(new);
- rb_start=rb_pointer=new;
- }}}
- /* the relblock has been allocated */
-
- /* now move the sgc free lists into place. alt_free should
- contain the others */
-
- for (i= t_start; i < t_contiguous ; i++)
- if ((bug1= TM_BASE_TYPE_P(i))
- && (np=(tm=tm_of(i))->tm_sgc))
- {object f=tm->tm_free ,x,y,next;
- int count=0;
- x=y=0;
- bug2=(tm_table[i].tm_type == (enum type) i);
- while (f!=0)
- {next=F_LINK(f);
- #ifdef SDEBUG
- if (f->d.m!=FREE)
- printf("Not FREE in freelist f=%d",f);
- #endif
- if (ON_SGC_PAGE(f))
- { F_LINK(f) =x;
- f->d.s = SGC_RECENT;
- x=f;
- count++;
- }
- else
- {F_LINK(f)=y;
- f->d.s = SGC_NORMAL;
- y=f;}
- f=next;
- }
- tm->tm_free = x;
- tm->tm_alt_free = y;
- tm->tm_alt_nfree = tm->tm_nfree - count;
- tm->tm_nfree=count;
- }
-
- /* Whew. We have now allocated the sgc space
- and modified the tm_table;
- Turn memory protection on for the pages which are writable.
- */
- memory_protect(1);
- sgc_enabled=1;
- if(siVnotify_gbc->s.s_dbind != Cnil)
- {printf("[SGC on]"); fflush(stdout);}
-
- }
-
- sgc_quit()
- { struct typemanager *tm;
- int i,np;
- memory_protect(0);
- if(siVnotify_gbc->s.s_dbind != Cnil)
- {printf("[SGC off]"); fflush(stdout);}
- if (sgc_enabled==0) return 0;
- sgc_enabled=0;
- rb_start = old_rb_start;
- for (i= t_start; i < t_contiguous ; i++)
- if (TM_BASE_TYPE_P(i))
- {tm=tm_of(i);
- if (np=tm->tm_sgc)
- {object f,y;
- f=tm->tm_free;
- if (f==0) tm->tm_free=tm->tm_alt_free;
- else
- /* tack the alt_free onto the end of free */
- {
- #ifdef SDEBUG
- int count=0;
- f=tm->tm_free;
- while(y= F_LINK(f))
- {if(y->d.s != SGC_RECENT)
- printf("[bad %d]",y);
- count++; f=y;}
-
- count=0;
- if (f=tm->tm_alt_free)
- while(y= F_LINK(f))
- {
- if(y->d.s != SGC_NORMAL)
- printf("[alt_bad %d]",y);
- count++; f=y;}
-
- #endif
- f=tm->tm_free;
- while(y= F_LINK(f))
- f=y;
- F_LINK(f)=tm->tm_alt_free;
- }
- /* tm->tm_free has all of the free objects */
- tm->tm_nfree += tm->tm_alt_nfree;
- tm->tm_alt_nfree = 0;
- tm->tm_alt_free = 0;
-
- /* remove the recent flag from any objects on sgc pages */
- {int hp=page(heap_end);
- int i,j;
- char t = (char) tm->tm_type;
- char *p;
- for (i=0 ; i < hp; i++)
- if (type_map[i]==t && (sgc_type_map[i] & SGC_PAGE_FLAG))
- for (p= pagetochar(i),j = tm->tm_nppage;
- j > 0; --j, p += tm->tm_size)
- {((object) p)->d.s = SGC_NORMAL;}}
-
-
-
- }}
- }
-
- void
- make_writable(beg,i)
- int beg,i;
- {if (i > beg)
- {beg=ROUND_DOWN_PAGE_NO(beg);
- i=ROUND_UP_PAGE_NO(i);
- {int k=beg;
- while(k <i )
- sgc_type_map[k++] |= SGC_TEMP_WRITABLE;
- }
- sgc_mprotect(beg, i-beg, SGC_WRITABLE);
- ;}
- }
-
- int debug_fault =0;
- int fault_count =0;
- extern char *etext;
- void
- memprotect_handler(sig, code, scp, addr)
- int sig, code;
- struct sigcontext *scp;
- char *addr;
- {int p;
- int j=page_multiple;
- #ifdef GET_FAULT_ADDR
- addr=GET_FAULT_ADDR(sig,code,scp,addr);
- debug_fault = (int) addr;
- #ifdef DEBUG_MPROTECT
- printf("fault:0x%x [%d] (%d)",addr,page(addr),addr >= core_end);
- #endif
- if (addr >= core_end || (unsigned int)addr < DBEGIN)
- {if (fault_count > 300) error("fault count to high");
- fault_count ++;
- INSTALL_MPROTECT_HANDLER;
- return;}
-
- #endif
- p = page(addr);
- p = ROUND_DOWN_PAGE_NO(p);
- if (p >= first_protectable_page
- && addr < core_end
- && !(WRITABLE_PAGE_P(p)))
- {/* CHECK_RANGE(p,1); */
- #ifdef DEBUG_MPROTECT
- printf("mprotect(0x%x,%x,0x%x)\n",pagetochar(p),page_multiple * PAGESIZE, sbrk(0));
- fflush(stdout);
- #endif
- mprotect(pagetochar(p),page_multiple * PAGESIZE, PROT_READ_WRITE);
- while (--j >= 0)
- sgc_type_map[p+j]= sgc_type_map[p+j] | SGC_TEMP_WRITABLE;
-
- #ifndef BSD
- INSTALL_MPROTECT_HANDLER;
- #endif
-
- return;
- }
-
- #ifndef BSD
- INSTALL_MPROTECT_HANDLER;
- #endif
- /* if (SIGSEGV == SIGPROTV) */
- END:
- segmentation_catcher();
- return;
- }
-
- sgc_mprotect(pbeg,n,writable)
- { /* CHECK_RANGE(pbeg,n); */
- #ifdef DEBUG_MPROTECT
- printf("prot[%d,%d,(%d),%s]\n",pbeg,pbeg+n,writable & SGC_WRITABLE,
- (writable & SGC_WRITABLE ? "writable" : "not writable"));
- fflush(stdout);
- #endif
- if(mprotect(pagetochar(pbeg),n*PAGESIZE,
- (writable & SGC_WRITABLE ? PROT_READ_WRITE : PROT_READ)))
- FEerror("Couldn't protect");}
-
-
- /* for page numbers from beg below end,
- if one page in a a page_multiple grouping is writable,the
- rest must be */
-
- fix_for_page_multiple(beg,end)
- {int i,j;
- char *p;
- int writable;
- beg = ROUND_DOWN_PAGE_NO(beg);
- for (i = beg ; i < end; i = i+ page_multiple){
- p = sgc_type_map + i;
- j = page_multiple;
- writable = ((*p++) & SGC_WRITABLE);
- if (writable)
- /* all pages must be */
- { while (--j)
- if (((*p++) & SGC_WRITABLE) == 0)
- goto FIXIT;}
- else
- { while (--j)
- if ((*p++) & SGC_WRITABLE )
- goto FIXIT;}
- continue;
- FIXIT:
- j = page_multiple;
- p = sgc_type_map + i;
- while (--j >= 0 )
- { (*p++) |= SGC_WRITABLE;}}}
-
-
- memory_protect(on)
- int on;
- { int i,beg,end= page(core_end);
- int writable=1;
- extern void install_segmentation_catcher();
- if (first_protectable_page==0)
- {
- for (i=page_multiple; i< maxpage ; i++)
- if (type_map[i]!=t_other)
- break;
- else {
- /* We want page(0) to be non writable since that
- is the only check for 0 pointer in sgc */
- sgc_type_map[i] = SGC_PERM_WRITABLE;}
- first_protectable_page= ROUND_DOWN_PAGE_NO(i);}
- if(page_multiple > 1)
- fix_for_page_multiple(first_protectable_page,end);
- /* turning it off */
- if (on==0) {sgc_mprotect((first_protectable_page),
- (end - first_protectable_page), SGC_WRITABLE);
- install_segmentation_catcher();
- return;}
- /* write protect some pages by first write protecting them
- all and then selectively disabling */
- /* sgc_mprotect((first_protectable_page),
- (end - first_protectable_page), 0);
- */
- INSTALL_MPROTECT_HANDLER;
- beg=first_protectable_page;
- writable = WRITABLE_PAGE_P(beg);
- for (i=beg ; ++i<= end; )
- {int wri = WRITABLE_PAGE_P(i);
- if ((wri==0 && writable)
- || (writable ==0 && wri)
- || i == end)
- /* it is changing */
- {if (writable)
- make_writable(beg,i);
- else
- sgc_mprotect(beg,i-beg,writable);
- writable = wri;
- beg = i;}
- }
- }
-
- void
- siLsgc_on()
- {if (vs_base==vs_top)
- {vs_base[0]=(sgc_enabled ? Ct :Cnil);
- vs_top=vs_base+1; return;}
- check_arg(1);
- if(vs_base[0]==Cnil)
- {sgc_quit();}
- else {sgc_start();}}
-
-
- /* make permanently writable pages containing pointers p thru p+n-1 */
-
-
- void
- perm_writable(p,n)
- char *p;
- int n;
- {int beg=page(p);
- int end=page(PAGE_ROUND_UP(p+n));
- int i,must_protect=0;
- beg = ROUND_DOWN_PAGE_NO(beg);
- end = ROUND_UP_PAGE_NO(end);
- for (i=beg ; i < end ; i++)
- {if (sgc_enabled & !(WRITABLE_PAGE_P(i))) must_protect = 1;
- sgc_type_map [i] |= SGC_PERM_WRITABLE;}
- if(must_protect) make_writable(beg,end);}
-
-
-
- system_error()
- {FEerror("System error");}
-
-
-
-